package be.destin.abdera;

import java.io.IOException;
import java.util.StringTokenizer;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.abdera.protocol.server.Provider;
import org.apache.abdera.protocol.server.RequestContext;
import org.apache.abdera.protocol.server.impl.SimpleWorkspaceInfo;
import org.apache.abdera.protocol.server.servlet.AbderaServlet;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.configuration.CayenneRuntime;
import org.apache.cayenne.configuration.web.WebUtil;
import org.apache.log4j.Logger;

import be.destin.skos.core.NoScheme;
import be.destin.skos.core.SchemeInterface;
import be.destin.skos.core.SkosManager;
import be.destin.skos.html.SkosHtmlManager;

/**
 * 
 */

/**
 * @author Christophe Dupriez
 * Abdera Servlet
 * Provider
 * Collection Adapter
 * Workspace Manager
 * Target Resolver / Target Builder
 * Filter
 * Workspace Metadata (WorkspaceInfo, CollectionInfo, CategoriesInfo, CategoryInfo)
 * 
 * https://cwiki.apache.org/confluence/display/ABDERA/Your+first+AtomPub+Server
 * https://cwiki.apache.org/confluence/download/attachments/69763/abderaserverguide.pdf?version=2&modificationDate=1201296071000
 * 
 * AtomPub Concept	Abdera Classes		Description 
 * Service			Provider			Providers provide the implementation of an AtomPub service. In general you should be able to just use the DefaultProvider which we will be using it as we construct our service.
 * Workspace		WorkspaceInfo		The WorkspaceInfo class provides metadata about your workspace for the services document. 
 * 					WorkspaceManager	The WorkspaceManager provides a way for you to list out the workspaces in a service.
 * Collection		CollectionAdapter	A CollectionAdapter is where your business logic will lie and allows you to implement the basic GET/DELETE/POST/etc operations for an AtomPub Collection.
 *
 */
public class AskosiProviderServlet extends AbderaServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	Logger log = Logger.getLogger(AskosiProviderServlet.class);
	
	static SkosManager skosManager = null;
	static final public String CURRENT_USER_ATTRIBUTE = "AbderaUser";
	static final public String CURRENT_HTML_MANAGER = "SkosHtmlManager";
	static final String WorkspaceTitleConcept = "ASKOSI Concept Schemes";
	static String host = "";
	
	synchronized public void initAskosiSchemes () {
		if (skosManager == null) {
			ServletContext context = this.getServletContext();
			if (context == null) return;

			host = context.getInitParameter("base");
			if (host == null) host = System.getProperty("base");
			if (host == null) host = context.getContextPath(); // Application root is missing!

			String skosDirectory = context.getInitParameter(SkosHtmlManager.SKOSdirectoryParam);
			if (skosDirectory == null) skosDirectory = System.getProperty(SkosHtmlManager.SKOSdirectoryParam);
			skosManager = SkosManager.getInstance(skosDirectory);

			String proxy = context.getInitParameter(SkosManager.ApplicationProxyParam);
			if (proxy == null) proxy = System.getProperty(SkosManager.ApplicationProxyParam);
			skosManager.setApplicationProxy(proxy);
			skosManager.initApplication(SkosHtmlManager.askosiDisplayApplication,host);
			String toPreload = context.getInitParameter(SkosHtmlManager.SKOSpreloadParam);
			if (toPreload == null) toPreload = System.getProperty(SkosHtmlManager.SKOSpreloadParam);
			if (toPreload != null) {
				StringTokenizer st = new StringTokenizer(toPreload,";\n, ");
				while (st.hasMoreTokens()) {
					String codeScheme = st.nextToken();
					skosManager.openScheme(codeScheme);
				}
			}
		}
	}

	@Override 
	public void service(HttpServletRequest req,
			HttpServletResponse res) throws ServletException, IOException {
		req.setAttribute(CURRENT_USER_ATTRIBUTE, req.getRemoteUser());

		if (skosManager == null) {
			initAskosiSchemes();
		}
		if (skosManager != null) {
			SkosHtmlManager skosHtmlManager = new SkosHtmlManager(req, null, skosManager, SkosHtmlManager.askosiDisplayApplication);
			req.setAttribute(CURRENT_HTML_MANAGER, skosHtmlManager);
		}

		super.service(req, res);
		
	}

	/*
	 * The servlet just handles the creation of the RequestContext and the serialization of the ResponseContext.
	 * @see org.apache.abdera.protocol.server.servlet.AbderaServlet#createProvider()
	 */
	@Override
	protected Provider createProvider() {
		if (skosManager == null) {
			initAskosiSchemes();
			if (skosManager == null) return null;
		}

		SimpleWorkspaceInfo wi = new SimpleWorkspaceInfo();
		wi.setTitle(WorkspaceTitleConcept);
		for (SchemeInterface aScheme : skosManager.getSchemes().values()) {
			// Keep only the extension of NoScheme but NOT NoScheme itself !
			if (aScheme instanceof NoScheme && aScheme.getClass() != NoScheme.class) {
				ConceptCollectionAdapter ca = new ConceptCollectionAdapter(skosManager, (NoScheme)aScheme); 
				wi.addCollection(ca);
			}
		}

		ConceptProvider provider = new ConceptProvider(host,"concept.svc", wi, skosManager);
		provider.init(getAbdera(), null);
		return provider;
	}

}
